package com.basker.pisces.core.query.meta;

import java.text.MessageFormat;

import org.springframework.util.StringUtils;

import com.basker.pisces.core.enums.TableType;

public class TableDesc {

    private String name;
    private String alias;
    private String pkFieldName;
    private String fkFieldName;
    private transient TableDesc parentTable;
    private TableType type;

    private transient PkFieldDesc pkField;
    private transient ReferenceFieldDesc fkField;
    private FieldDescCollection fields = new FieldDescCollection(this);

    /**
     * 构造函数
     *
     * @param name        表名
     * @param pkFieldName 主键字段名
     */
    public TableDesc(String name, String pkFieldName) {
        this(name, null, pkFieldName);
    }

    /**
     * 构造函数
     *
     * @param name        表名
     * @param pkFieldId   主键字段的标识
     * @param pkFieldName 主键字段名
     */
    public TableDesc(String name, String pkFieldId, String pkFieldName) {
        this.name = name;
        this.pkFieldName = pkFieldName;

        this.pkField = this.createPkFielfDesc(pkFieldId, pkFieldName);
    }

    /**
     * 表别名
     *
     * @return
     */
    public String getAlias() {
        return alias;
    }

    /**
     * 字段集合
     *
     * @return
     */
    public FieldDescCollection getFields() {
        return fields;
    }

    /**
     * 对于引用表，该属性返回引用当前表的字段
     *
     * @return
     */
    public ReferenceFieldDesc getFkField() {
        return fkField;
    }

    /**
     * 外键字段名，只有一对一子表和一对多子表才会有外键
     *
     * @return 外键字段名
     */
    public String getFkFieldName() {
        return fkFieldName;
    }

    /**
     * 完整的外键字段名
     *
     * @return 表别名.外键字段名
     */
    public String getFkFullFieldName() {
        if (!StringUtils.isEmpty(this.fkFieldName)) {
            return this.getFullFieldName(this.fkFieldName);
        }

        return null;
    }

    /**
     * 完整的字段名
     *
     * @param fieldName
     * @return 表别名.字段名
     */
    public String getFullFieldName(String fieldName) {
        return MessageFormat.format("{0}.{1}", alias, fieldName);
    }

    /**
     * 表等级，主表为0，子表为父表层级+1，扩展表、关联表与父表为同一级； 表等级的意义在于，同一级表在查询时可以通过联表拼接，不再同一级的需要用exist拼接
     *
     * @return
     */
    public int getLevel() {
        if (this.parentTable == null) {
            return 0;
        }

        if (TableType.Reference.equals(this.type)) {
            return this.parentTable.getLevel();
        }

        if (TableType.Sub.equals(type)) {
            return this.parentTable.getLevel();
        }

        if (TableType.Child.equals(this.type)) {
            return this.parentTable.getLevel() + 1;
        }

        return 0;
    }

    /**
     * 表名
     *
     * @return
     */
    public String getName() {
        return name;
    }

    /**
     * 获取当前表的父表，需要说明的是，对于关联表，其父表就是被关联字段的所属表
     *
     * @return
     */
    public TableDesc getParentTable() {
        return parentTable;
    }

    public PkFieldDesc getPkField() {
        return pkField;
    }

    /**
     * 主键字段名
     *
     * @return
     */
    public String getPkFieldName() {
        return pkFieldName;
    }

    /**
     * 完整的主键字段名
     *
     * @return 表别名.主键字段名
     */
    public String getPkFullFieldName() {
        return this.getFullFieldName(this.pkFieldName);
    }

    /**
     * 表类型
     *
     * @return
     */
    public TableType getType() {
        return type;
    }

    /**
     * 是否是引用表
     *
     * @return
     */
    public boolean isReferenceTable() {
        return TableType.Reference.equals(this.type);
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public void setFkField(ReferenceFieldDesc fkField) {
        this.fkField = fkField;
    }

    public void setFkFieldName(String fkFieldName) {
        this.fkFieldName = fkFieldName;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setParentTable(TableDesc parentTable) {
        this.parentTable = parentTable;
    }

    public void setPkFieldName(String pkFieldName) {
        this.pkFieldName = pkFieldName;
    }

    public void setType(TableType type) {
        this.type = type;
    }

    @Override
    public String toString() {
        if (StringUtils.isEmpty(this.alias)) {
            return this.name;
        }

        return MessageFormat.format("{0} {1}", this.name, this.alias);
    }

    protected PkFieldDesc createPkFielfDesc(String pkFieldId, String pkFieldName) {
        PkFieldDesc field = new PkFieldDesc();

        field.setId(pkFieldId == null ? pkFieldName : pkFieldId);
        field.setName(pkFieldName);
        field.setAlias(pkFieldId);
        field.setHostTable(this);

        return field;
    }

}
